<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Ruby Access Control: Ruby Study Notes - Best Ruby Guide, Ruby Tutorial</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="Ruby Study Notes - Best Ruby Guide, Ruby Tutorial" />
<meta name="keywords" content="ruby study notes,ruby access control,ruby guide,free ruby programming course,best ruby guide,ruby tutorials,ruby tutorial,learn ruby,ruby,ruby on rails,ruby rails,ruby learning,ruby tutoring,learning ruby,ruby programming,ruby on rails development,ruby training" />
<meta name="Distribution" content="Global" />
<meta name="author" content="Satish Talim / Original design: Erwin Aligam - ealigam@gmail.com" />
<meta name="copyright" content="Satish Talim 2007 and beyond..." />
<meta name="verify-v1" content="rFu86se+IkbtF+bH8mgJBKwU5HnKaSd8Ghw9umXQOkM=" />
<meta name="robots" content="index,follow" />
<meta http-equiv="Expires" content="0" />
<meta name="revisit-after" content="1 days" />
<link rel="stylesheet" href="/images/NewOrange.css" type="text/css" />
<link rel="stylesheet" href="/images/syntaxhighlighter.css" type="text/css" />
<link rel="icon" type="image/ico" href="/images/favicon.ico" />
<!-- Google +1 button code -->
<link rel="canonical" href="/satishtalim/ruby_access_control.html" />
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>

<!-- Google Analytics code -->
<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-59044-10']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>
<!-- Google Analytics code ends -->
</head>

<body>
<!-- wrap starts here -->
<div id="wrap">

    <div id="header">

        <h1 id="logo">Ruby<span class="orange">Learning.github.io</span></h1>
        <h2 id="slogan">Helping Ruby Programmers become Awesome!</h2>

    </div>

    <div id="menu">
        <ul>
            <li><a href="/" title="Home page for rubylearning.github.io">Home</a></li>
            <li><a href="/satishtalim/tutorial.html" title="Get started Learning Ruby here...">Tutorial</a></li>
            <li><a href="/download/downloads.html" title="Download this tutorial as an eBook">Downloads</a></li>
            <li><a href="/other/testimonials.html" title="People around the world who benefited from this site">Testimonials</a></li>
            <li><a href="/other/certification.html" title="Get certified in Ruby">Certification</a></li>
            <li><a href="/satishtalim/ruby_guide.html" title="Ruby Guide, Mentor">Mentor</a></li>
            <li><a href="https://blog.rubylearning.github.io/" title="Ruby blog of Learning Ruby site">Blog</a></li>
            <li><a href="/satishtalim/tutorial.html" title="Online Ruby Course">Online Course</a></li>
            <li><a href="http://ruby-challenge.rubylearning.github.io/" title="Ruby Programming Challenge for Newbies">Challenge</a></li>
            <li><a href="/satishtalim/about.html" title="Information about Satish Talim">About</a></li>
        </ul>
    </div>

    <!-- content-wrap starts here -->
    <div id="content-wrap">


            <div id="main">

                <div id="main-inner"> <a name="TemplateInfo"></a>
                <h1>Ruby Access Control</h1>

                <p class="post-footer align-right">
                  <strong>
                    <a href="/satishtalim/ruby_overloading_methods.html">&lt;Overloading Methods | </a>
                    <a href="/satishtalim/tutorial.html">TOC | </a>
                    <a href="/satishtalim/ruby_exceptions.html">Exceptions&gt;</a>
                  </strong>
                </p>

                <p><em>The only easy way to change an object's state in Ruby is by calling one of its methods. Control access to the methods, and you have controlled access to the object</em>. A good rule of the thumb is never to expose methods that could leave an object in an invalid state.</p>

                <p>Ruby gives you three levels of protection:</p>

                <ol>
                  <li><strong>Public</strong> methods can be called by everyone - no access control is enforced. <em>A class's instance methods (these do not belong only to one object; instead, every instance of the class can call them) are public by default</em>; anyone can call them. The <strong>initialize</strong> method is always private.</li>
                  <li><strong>Protected</strong> methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family. However, usage of <strong>protected</strong> is limited.</li>
                  <li><strong>Private</strong> methods cannot be called with an explicit receiver - the receiver is always <strong>self</strong>. This means that private methods can be called only in the context of the current object; you cannot invoke another object's private methods.</li>
                </ol>

                <p>Access control is determined dynamically, as the program runs, not statically. You will get an access violation only when the code attempts to execute the restricted method. Let us refer to the program <strong>p047classaccess.rb</strong> below:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                # p047classaccess.rb
                class ClassAccess
                  def m1          # this method is public
                  end
                  protected
                    def m2        # this method is protected
                    end
                  private
                    def m3        # this method is private
                    end
                end
                ca = ClassAccess.new
                ca.m1
                #ca.m2
                #ca.m3
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>If you remove the comments of the last two statements in the above program, you will get an access violation runtime error.</p>

                <p>Alternatively, you can set access levels of named methods by listing them as arguments to the access control functions.</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                class ClassAccess
                  def m1       # this method is public
                  end
                  public :m1
                  protected :m2, :m3
                  private :m4, :m5
                end
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>Here is an example (<strong>p047zclassaccess.rb</strong>) for 'protected' access control:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                # p047zclassaccess.rb
                class Person
                  def initialize(age)
                    @age = age
                  end
                  def age
                    @age
                  end
                  def compare_age(c)
                    if c.age > age
                      "The other object's age is bigger."
                    else
                      "The other object's age is the same or smaller."
                    end
                  end
                  protected :age
                end

                chris = Person.new(25)
                marcos = Person.new(34)
                puts chris.compare_age(marcos)
                #puts chris.age
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>The output is:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                >ruby p047zclassaccess.rb
                The other object's age is bigger.
                >Exit code: 0
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>In the preceding example, we compare one Person instance with another Person instance. The comparison, however, depends on the result of a call to the method age. The object doing the comparing (chris, in the example) has to ask the other object (marcos) to execute its age method. So, age can't be private.<br /><br />That's where the protected level comes in. With age protected rather than private, chris can ask marcos to execute age, because  chris and marcos are both instances of the same class. But if you try to call the age method of a Person object when self is anything other than a Person object, the method will fail.<br /><br />A protected method is thus like a private method, but with an exemption for cases where the class of self (chris) and the class of the object having the method called on it (marcos) are the same.<br /><br />Note that if you remove the comment from the last statement in the program ie. when you use age directly, Ruby throws an exception.</p>

                <p class="post-note">In Ruby, <strong>public, private</strong> and <strong>protected</strong> apply only to methods. Instance and class variables are encapsulated and effectively private, and constants are effectively public. There is no way to make an instance variable accessible from outside a class (except by defining an accessor method). And there is no way to define a constant that is inaccessible to outside use.</p>

                <h3>Overriding private methods</h3>

                <p>Private methods cannot normally be invoked from outside the class that defines them. But they are inherited by subclasses. This means that subclasses can invoke them and can override them.</p>

                <p class="post-note">Classes often use private methods as internal helper methods. They are not part of the public API of the class and are not intended to be visible. If you happen to define a method in your subclass that has the same name as a private method in the superclass, you will have inadvertently overridden the superclass's internal utility method, and this will almost certainly cause unintended behavior.</p>

                <h3>Accessor methods</h3>

                <p><em>Encapsulation</em> is achieved when the instance variables are private to an object and you have public getters and setters (in Ruby, we call them attribute readers and attribute writers). To make instance variables available, Ruby provides <em>accessor methods</em> that return their values. The program <strong>p048accessor.rb</strong> illustrates the same.</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                # p048accessor.rb
                # First without accessor methods
                class Song
                  def initialize(name, artist)
                    @name     = name
                    @artist   = artist
                  end
                  def name
                    @name
                  end
                  def artist
                    @artist
                  end
                end

                song = Song.new("Brazil", "Ivete Sangalo")
                puts song.name
                puts song.artist

                # Now, with accessor methods
                class Song
                  def initialize(name, artist)
                    @name     = name
                    @artist   = artist
                  end
                  attr_reader :name, :artist  # create reader only
                  # For creating reader and writer methods
                  # attr_accessor :name
                  # For creating writer methods
                  # attr_writer :name

                end

                song = Song.new("Brazil", "Ivete Sangalo")
                puts song.name
                puts song.artist
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <h4>Are instance variables inherited by a sub-class?</h4>

                <p>David Black, the author of <em>Ruby for Rails</em>, has this to say: Instance variables are per-object, not per-class, and <em>they're not inherited</em>. But if a method uses one, and that method is available to subclasses, then it will still use the variable -- but "the variable" in the sense of one per object. See the following program - <strong>p049instvarinherit.rb</strong>:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                # p049instvarinherit.rb
                class C
                  def initialize
                    @n = 100
                  end

                  def increase_n
                    @n *= 20
                  end
                end

                class D &lt; C
                  def show_n
                    puts "n is #{@n}"
                  end
                end

                d = D.new
                d.increase_n
                d.show_n
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>The output is:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                >ruby p049instvarinherit.rb
                n is 2000
                >Exit code: 0
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p><em>The @n in D's methods is the same name (for each instance) as the one in C.</em></p>

                <p class="post-note">All Ruby objects have a set of instance variables. These are not defined by the object's class - they are simply created when a value is assigned to them. Because instance variables are not defined by a class, they are unrelated to subclassing and the inheritance mechanism.</p>

                <h3>Top-level methods</h3>

                <p>When you write code at the top level, Ruby provides you automatically with a default <strong>self</strong>. This object is a direct instance of <strong>Object</strong>. When you ask it to describe itself:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                puts self
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>it says:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                main
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>The object <strong>main</strong> is the current object as soon as your program starts up.<br /><br />Suppose you define a method at the top level:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                def talk
                  puts "Hello"
                end
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>Who, or what, does the method belong to? It's not inside a class or module definition block, so it doesn't appear to be an instance method of a class or module. It's not attached to any particular object (as in def obj.talk). What is it? When we define top-level methods, we're actually creating (private) instance methods for class <b>Object</b>.</p>

                <p>Because top-level methods are private, you can't call them with an explicit receiver; you can only call them by using the implied receiver, <strong>self</strong>. That means <strong>self</strong> must be an object on whose method search path the given top-level method lies. But every object's search path includes the <strong>Kernel</strong> module, because the class <strong>Object</strong> mixes in <strong>Kernel</strong>, and every object's class has <strong>Object</strong> as an ancestor. That means you can <em>always</em> call any top-level method, wherever you are in your program. It also means you can <em>never</em> use an explicit receiver on a top-level method.</p>

                <p>From our earliest examples onward, we've been making bareword-style calls to <strong>puts</strong> and <strong>print</strong>, like this one:</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                puts 'Hello'
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p><strong>puts</strong> and <strong>print</strong> are built-in private instance methods of <strong>Kernel</strong>. That's why you can - indeed, must - call them without a receiver.<br /><br />We shall talk about <a href="/satishtalim/ruby_self.html">self</a> in more details, later.</p>

                <p style="background-color: #FAFAFA; padding: 5px; margin-top: 20px; font-size: 65%;"><strong>Note</strong>: The Ruby Logo is Copyright (c) 2006, Yukihiro Matsumoto. I have made extensive references to information, related to Ruby, available in the public domain (wikis and the blogs, articles of various <span style="font-weight: bold;" title="Click Gurus on the menu above">Ruby Gurus</span>), my acknowledgment and thanks to all of them. Much of the material on <a href="/">rubylearning.github.io</a> and in the course at <a href="http://rubylearning.org/">rubylearning.org</a> is drawn <strong>primarily</strong> from the <strong>Programming Ruby book</strong>, available from <a href="http://pragprog.com/book/ruby3/programming-ruby-1-9-2-0">The Pragmatic Bookshelf</a>.</p>

                <p class="post-footer align-right">
                  <strong>
                    <a href="/satishtalim/ruby_overloading_methods.html">&lt;Overloading Methods | </a>
                    <a href="/satishtalim/tutorial.html">TOC | </a>
                    <a href="/satishtalim/ruby_exceptions.html">Exceptions&gt;</a>
                  </strong>
                </p>

            </div>
            <!-- main inner ends here -->
        </div>

            <div id="rightbar">

            </div>

    <!-- content-wrap ends here -->
    </div>

<!-- wrap ends here -->
</div>

<!-- footer starts here -->
<div id="footer">
    <!-- CHANGE THE FOOTER -->
    <p>&copy; 2006-2021 <strong>rubylearning.github.io - A Ruby Tutorial</strong>&nbsp;&nbsp;Page Updated: 5th Jan. 2021 | Design: <a href="mailto:ealigam@gmail.com">Erwin Aligam</a> | Valid: <a href="http://validator.w3.org/check/referer">XHTML</a> | <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/">Home</a> | <a href="/privacy.html">Privacy</a> | <a href="/sitemap.html">Sitemap</a></p>
</div>

<!-- footer ends here -->

<!-- SyntaxHighlighter code -->
<script src="/js/shCore.js" type="text/javascript"></script>
<script src="/js/shBrushRuby.js" type="text/javascript"></script>
<script type="text/javascript">
dp.SyntaxHighlighter.HighlightAll('code');
</script>
<!-- SyntaxHighlighter code -->
</body>
</html>
